import os
import sys
from functools import reduce
from math import  exp, log,fabs,pow

"""
a1:  区间值模糊数 格式为([],[])

self.q: q值

a2:     区间值模糊数 格式为([],[])

编写时间:2022-7-2 
编写人:吴卓成
参考文献:Multiple-Attribute Group Decision-Making Based
on q-Rung Orthopair Fuzzy Power Maclaurin
Symmetric Mean Operators
"""

from Utilities.AutoGetOperator.selectPackage import get_func

AcezelAlsina=get_func(r'Operators/OperationOperators/AcezelAlsina.py','AcezelAlsina')
class AcezelAlsinaPowAverage(AcezelAlsina):
    def get_ta(self, i_a, *waste1, **waste2):
        """
        function : 计算 TA ，需要调用 get_sup
        i_a      : 传入模糊数 ai 的下标 int
        return   : T(ai) 的值
        atttention  : 调用的是self.data_list 
        """
        ta = 0
        # T(ai) = 累加 Sup(ai, aj)
        for j_a in range(len(self.data_list)):
            if j_a != i_a:         # 公式要求 i != j
                ta += self.get_sup(self.data_list[i_a], self.data_list[j_a]) * self.weight_list[i_a]
        return ta

    def get_sup(self, a1, a2, *waste1, **waste2):
        """ √
            function : 求支撑度度
            a1       : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2       : 一个模糊集, 形式:（[x,y]，[x,y]）
            return   : sup 的值
        """
        return (1 - self.get_d(a1, a2))

    def get_d(self, a1, a2, *waste1, **waste2):
        """ √
            function : 求用于计算支撑度中用到的 d
            a1       : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2       : 一个模糊集, 形式:（[x,y]，[x,y]）
            return   : d 的值
        """
        # 提取隶属区间的上下界、非隶属区间的上下界限、犹豫度的上下界限
        u_1_f, u_1_r, v_1_f, v_1_r, pi_1_f, pi_1_r = *a1[0], *a1[1], *self.get_pi(a1)
        u_2_f, u_2_r, v_2_f, v_2_r, pi_2_f, pi_2_r = *a2[0], *a2[1], *self.get_pi(a2)

        # 将公式分为三个部分：隶属区间u、费隶属区间v、犹豫度π
        part_u = fabs(u_1_f ** self.q - u_2_f ** self.q) + fabs(u_1_r ** self.q - u_2_r ** self.q)
        part_v = fabs(v_1_f ** self.q - v_2_f ** self.q) + fabs(v_1_r ** self.q - v_2_r ** self.q)
        part_r = fabs(pi_1_f ** self.q - pi_2_f ** self.q) + fabs(pi_1_r ** self.q - pi_2_r ** self.q)

        # 整合三个部分的公式
        d_value = 1/4 * (part_u + part_v + part_r)
        return d_value

    def get_pi(self, a, *waste1, **waste2):
        """
            function : 求犹豫度 —— 求 d 即 get_d 中会用到
            a        : 一个模糊集, 形式:（[x,y]，[x,y]）
            return   : 犹豫度列表，形式： [x,y]
        """
        pi_f = pow(1 - pow(a[0][1], self.q) - pow(a[1][1], self.q), 1/self.q)
        # print(1 - pow(a[0][0], self.q) - pow(a[1][0], self.q))
        pi_r = pow(1 - pow(a[0][0], self.q) - pow(a[1][0], self.q), 1/self.q)
        return [pi_f, pi_r]

    def getResult(self, *waste1, **waste2):
        """
            function : 计算出 AA 算子和 PA 算子算子融合
            return   : AAPGA 集结后的数据结果，形式：（[x,y]，[x,y]）
        """
        ta_add = 0  # 记录 T(ai)+1 累加部分
        print(self.data_list)
        print(self.weight_list)
        for i_a in range(len(self.data_list)):
            
            ta_add += (1 + self.get_ta(i_a)) * self.weight_list[i_a]

        # 根据原始公式调用运算符号进行
      
        a_result = self.pow(self.data_list[0], ((1 + self.get_ta(0)) * self.weight_list[0]) / ta_add)
        for i_a in range(1, len(self.data_list)):
            a1 = a_result
            a2 = self.pow(self.data_list[i_a], ((1 + self.get_ta(i_a)) * self.weight_list[i_a]) / ta_add)
            a_result = self.multi(a1, a2)
        return a_result
class AcezelAlsinaPowAverageWA(AcezelAlsinaPowAverage):
    def getResult(self, *waste1, **waste2):
        res_t=0# wi*（1+TT（xi））累和的结果存放于这个变量中
        for i in range(len(self.data_list)):#求取 Wi *（1+TT（xi）)
            res_t+=((1+self.get_ta(i))*self.weight_list[i])
        data_list=self.data_list
        res=self.multi(self.multi(data_list[0],((1+self.get_ta(0))*self.weight[0])),1/res_t)
        data_list=data_list[1::]
        for index ,enum in enumerate(data_list,start=1):
            res_temp=self.multi(self.multi(enum,((1+self.get_ta(index))*self.weight[index])),1/res_t)
            res=self.add(res,res_temp)
        return res
class AcezelAlsinaPowAverageOWA(AcezelAlsinaPowAverage):
    def getResult(self, *waste1, **waste2):    
        data_list= self.sortdata()#根据得分函数排序,获取数据
        #先看def get_ta 的注释  调用的是self.data_list
        data_temp=self.data_list
        self.data_list=data_list#跟换值 因为 def get_ta 写法的特殊性
        res_t=0# wi*（1+TT（xi））累和的结果存放于这个变量中
        for i in range(len(self.data_list)):#求取（1+TT（xi）累和）
            res_t+=((1+self.get_ta(i))*self.weight_list[i])
        data_list=self.data_list
        res=self.multi(self.multi(data_list[0],((1+self.get_ta(0))*self.weight[0])),1/res_t)
        data_list=data_list[1::]
        for index ,enum in enumerate(data_list,start=1):
            res_temp=self.multi(self.multi(enum,((1+self.get_ta(index))*self.weight[index])),1/res_t)
            res=self.add(res,res_temp)
        self.data_list=data_temp
        return res
class AcezelAlsinaPowAverageGA(AcezelAlsinaPowAverage):
    def getResult(self, *waste1, **waste2):
        res_t=0# （1+TT（xi））累和的结果存放于这个变量中
        for i in range(len(self.data_list)):#求取（1+TT（xi）累和）
            res_t+=((1+self.get_ta(i)))
        data_list=self.data_list
        res=self.pow(data_list[0],(1+self.get_ta(0))/res_t)
        data_list=data_list[1::]
        for index ,enum in enumerate(data_list,start=1):
            res_temp=self.pow(enum,(1+self.get_ta(index))/res_t)
            res=self.kmulti(res,res_temp)
        return res
class AcezelAlsinaPowAverageWGA(AcezelAlsinaPowAverage):
    def getResult(self, *waste1, **waste2):
        res_t=0# wi*（1+TT（xi））累和的结果存放于这个变量中
        for i in range(len(self.data_list)):#求取 Wi *（1+TT（xi）)
            res_t+=((1+self.get_ta(i))*self.weight_list[i])
        data_list=self.data_list
        res=self.pow(data_list[0],(self.weight[0]*(1+self.get_ta(0)))/res_t)
        data_list=data_list[1::]
        for index ,enum in enumerate(data_list,start=1):
            res_temp=self.pow(enum,(self.weight[index]*(1+self.get_ta(index)))/res_t)
            res=self.kmulti(res,res_temp)
        return res
if __name__ == '__main__':
    data_list=[([0.31, 0.24], [0.73, 0.72]), ([0.97, 0.12], [0.12, 0.05]),
    ([0.8, 0.52], [0.73, 0.15]), ([0.91, 0.49], [0.42, 0.47]),([0.95, 0.06], [0.19, 0.1])]
    weight_list=[0.1, 0.2, 0.3, 0.1, 0.3],
    Pa =AcezelAlsinaPowAverage(data_list)
    #伟康数据初始设置，对比数据 得到一致结果
    # Pa.set_q(2)
    # Pa.set_x(2)
    # Pa.set_y(0.5)
    # Pa.set_z(0.5)
    # Pa = GA(list1)
    # Pa = WA(list1,weight_list)
    # Pa = WGA(list1,weight_list)
    # Pa = OWA(list1,weight_list)
    print(Pa.getResult())
    

        
        





